/*!
    \file    main.c
    \brief   GD30AD3340 test demo

    \version 2024-10-08, V1.0.0, demo for GD30AD3340
*/

#include "gd32f30x.h"
#include "systick.h"
#include <stdio.h>
#include "gd30ad3x40.h"
#include "uart_print.h"
#include "i2c_port.h"
#include "main.h"

int16_t adc_16bit_int;
float ADC_Value;
float pga;
uint8_t i;
uint32_t sample_count;
uint32_t number_of_sample;

#define POSITIVE_FS 0x7FFF
#define NEGATIVE_FS 0x8000
#define ADC_DATA    32768

/*!
    \brief      delay us
    \param[in]  t: delay time
    \param[out] none
    \retval     none
*/
void delay_us(uint32_t t)
{
    uint16_t i;
    while (t--){
         i = 10;
         while(i--);
   }
}

/*!
    \brief      GD30AD3x40 Config Register
    \param[in]  TnputMUX
                only one parameter can be selected which is shown as below:
      \arg      AD3x40_SINGLE_END
      \arg      AD3x40_DUAL_END
    \param[in]  Channel
                only one parameter can be selected which is shown as below:
      \arg      0: AD3x40_REG_CONFIG_MUX_DIFF_0_1(AD3x40_DUAL_END) or AD3x40_REG_CONFIG_MUX_SINGLE_0(AD3x40_SINGLE_END)
      \arg      1: AD3x40_REG_CONFIG_MUX_DIFF_0_3(AD3x40_DUAL_END) or AD3x40_REG_CONFIG_MUX_SINGLE_1(AD3x40_SINGLE_END)
      \arg      2: AD3x40_REG_CONFIG_MUX_DIFF_1_3(AD3x40_DUAL_END) or AD3x40_REG_CONFIG_MUX_SINGLE_2(AD3x40_SINGLE_END)
      \arg      3: AD3x40_REG_CONFIG_MUX_DIFF_2_3(AD3x40_DUAL_END) or AD3x40_REG_CONFIG_MUX_SINGLE_3(AD3x40_SINGLE_END)
    \param[out] none
    \retval     none
*/
void AD3x40_reg_Config(uint8_t InputMUX,uint8_t Channel)
{
    /* Start with default values */
    AD3x40_CONFIG  = AD3x40_REG_CONFIG_CQUE_1CONV  |            /* enable alert/rdy PIN */
    AD3x40_REG_CONFIG_CLAT_NONLAT  |                            /* Non-latching (default val) */
    AD3x40_REG_CONFIG_CPOL_ACTVLOW |                            /* Alert/Rdy active low   (default val) */
    AD3x40_REG_CONFIG_CMODE_TRAD   |                            /* Traditional comparator (default val) */
    AD3x40_REG_CONFIG_DR_1000SPS;                               /* 1000 samples per second (default) */
    
    /* Set PGA/voltage range */
    AD3x40_CONFIG |= AD3x40_REG_CONFIG_PGA_4_096V;
    
    uint16_t PGA_SET = AD3x40_CONFIG & AD3x40_REG_CONFIG_PGA_MASK;
    if(PGA_SET == AD3x40_REG_CONFIG_PGA_6_144V){
        pga = 6.144;
    }else if(PGA_SET == AD3x40_REG_CONFIG_PGA_4_096V){
        pga = 4.096;
    }else if(PGA_SET == AD3x40_REG_CONFIG_PGA_2_048V){
        pga = 2.048;
    }else if(PGA_SET == AD3x40_REG_CONFIG_PGA_1_024V){
        pga = 1.024;
    }else if(PGA_SET == AD3x40_REG_CONFIG_PGA_0_512V){
        pga = 0.512;
    }else if(PGA_SET == AD3x40_REG_CONFIG_PGA_0_256V){
        pga = 0.256;
    }else{
        pga = 0.064;
    }

    if(InputMUX == AD3x40_DUAL_END)
    {
        switch (Channel)
        {
        case (0):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_DIFF_0_1;
          break;
        case (1):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_DIFF_0_3;
          break;
        case (2):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_DIFF_1_3;
          break;
        case (3):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_DIFF_2_3;
          break;
        }
    }
    else if(InputMUX == AD3x40_SINGLE_END)
    {
        switch (Channel)
        {
        case (0):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_SINGLE_0;
          break;
        case (1):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_SINGLE_1;
          break;
        case (2):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_SINGLE_2;
          break;
        case (3):
          AD3x40_CONFIG |= AD3x40_REG_CONFIG_MUX_SINGLE_3;
          break;
        }
    }
    
    #ifndef CONTINUOUS_CONVERSION
        AD3x40_CONFIG |= AD3x40_REG_CONFIG_MODE_SINGLE;         /* Single-shot mode (default) */
        /*Set 'start single-conversion' bit */
        AD3x40_CONFIG |= AD3x40_REG_CONFIG_OS_SINGLE;

    #else
        AD3x40_CONFIG |= AD3x40_REG_CONFIG_MODE_CONTIN;         /*  Continuous conversion mode */
    #endif
}

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    uart_print_init();
    
    /* GD30AD3x40 config */
    ad3x40_gpio_init();
    ad3x40_i2c_gpio_init();
    ad3x40_i2c_init();

    ad3x40_write_regs(AD3x40_LO_THRESH_ADDRESS, 0x0000);
    delay_us(10);
    ad3x40_write_regs(AD3x40_HI_THRESH_ADDRESS, 0x8000);            /* enable the ALERT/RDY pin as a conversion ready pin */

    AD3x40_reg_Config(AD3x40_SINGLE_END,0);                         /* Channel 0 sample */
    ad3x40_write_regs(AD3x40_CONFIG_ADDRESS, AD3x40_CONFIG);
    
    printf("start conversion!\n\r");
    
    while(1) {
        
    }
}

/*!
    \brief      adc data conversion to voltage
    \param[in]  adc data
    \param[out] none
    \retval     voltage
*/
float adcdata_to_volt(uint16_t bin)
{
    int  _val;
    float adcValue;
    
    if(bin == NEGATIVE_FS){
        adcValue = -(pga*bin/ADC_DATA);
    }else{
        _val     =  bin&NEGATIVE_FS ?  (-((~bin+1)&POSITIVE_FS)):bin;
        adcValue = pga*_val/ADC_DATA;
    }
    
    return adcValue;
}

/*!
    \brief      this function handles EXTI0 exception
    \param[in]  none
    \param[out] none
    \retval     none
*/
void EXTI0_IRQHandler()
{
    if(RESET != exti_interrupt_flag_get(EXTI_0) )
    {
        exti_interrupt_flag_clear(EXTI_0);
        
        #ifndef CHANNEL_SWITCH_READ
            if(number_of_sample > Adc_Sample_Count){
                ad3x40_stop_conver();
                nvic_irq_disable(EXTI0_IRQn);
                usart_interrupt_disable(USART0, USART_INT_RBNE);
                number_of_sample = 0;
                printf("sampling over!\n\r");
            }else{
                adc_16bit_int = ad3340_read_data();
                ADC_Value = adcdata_to_volt(adc_16bit_int);
                printf("%d:%f\n",number_of_sample, ADC_Value);
                #ifdef CONTINUOUS_CONVERSION
                number_of_sample++;
                #else
                nvic_irq_disable(EXTI0_IRQn);
                usart_interrupt_disable(USART0, USART_INT_RBNE);
                #endif
            }
        #else
            if(number_of_sample > Adc_Sample_Count){
                ad3x40_stop_conver();
                nvic_irq_disable(EXTI0_IRQn);
                usart_interrupt_disable(USART0, USART_INT_RBNE);
                number_of_sample = 0;
                printf("sampling over!\n\r");
            }else{
                for(i=0;i<4;i++)
                {
                    AD3x40_reg_Config(AD3x40_SINGLE_END, i);
                    ad3x40_write_regs(AD3x40_CONFIG_ADDRESS,AD3x40_CONFIG);
                    delay_us(10000);
                    
                    adc_16bit_int = ad3340_read_data();
                    ADC_Value = adcdata_to_volt(adc_16bit_int);
                    
                    printf("%d:%d:%f\n",number_of_sample, i, ADC_Value);
                }
                #ifdef CONTINUOUS_CONVERSION
                number_of_sample++;
                #else
                nvic_irq_disable(EXTI0_IRQn);
                usart_interrupt_disable(USART0, USART_INT_RBNE);
                #endif
            }
            #ifndef CONTINUOUS_CONVERSION
                nvic_irq_disable(EXTI0_IRQn);
            #endif
        #endif
    }
}

#ifdef __ICCARM__
int putc(char c)
{
    usart_data_transmit(USART0,c);
    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    return c;
}
#else 
int fputc(int ch, FILE *f)
{
    usart_data_transmit(USART0,ch);
    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    return ch;

}
#endif


